from CardGame import permissions, game, cardcollection, parser, connections, errors

import unittest

args = {}
unimplemented = permissions.PermissionsController( args )
allowall = permissions.AllowAllController( args )
denyall = permissions.DenyAllController( args )

thetable = cardcollection.InMemoryCardCollectionController(
    {"CardA":{'x':0, 'y':0},
     "CardB":{'x':2, 'y':2},
     "CardC":{'x':4, 'y':1}},
    args)

drawdeck1 = \
    cardcollection.InMemoryCardCollectionController(
    {"Card1":{}, "Card2":{}, "Card3":{}},
    args)
    
hand1 = \
    cardcollection.InMemoryCardCollectionController(
    {"Card4":{}, "Card5":{}, "Card6":{}},
    args)
    
othercollection1 = \
    cardcollection.InMemoryCardCollectionController(
    {"Card7":{}, "Card8":{}, "Card9":{}},
    args)

thedecks = {"drawdeck1":drawdeck1}
thetables = {"table1":thetable}
thehands = {"hand1":hand1}
theothercollections = {"othercollection1":othercollection1}
thecardcollections = {"decks":thedecks, "tables":thetables,
                      "hands":thehands, "other":theothercollections}

theconnections = connections.StdInputConnectionsController( args )
theparser = parser.SampleParserController(theconnections, args)
theconnections.set_parser(theparser)

permissions_dict = {'bob': { 'move_card_coordinates': True },
                    'jeff': { 'move_card_coordinates': False }}

thepermissions = permissions.InMemoryController(permissions_dict)

thegame = game.GameController(permissions=thepermissions, 
                              cardcollections=thecardcollections)

params = {}

class UnimplementedTest(unittest.TestCase):
    def testPermissions(self):
        """Nothing other than __init__ should be implemented in this base class."""
        self.assertRaises(errors.UnimplementedError, unimplemented.allowed, "bob", "do_this", params)

class PermissionsTest(unittest.TestCase):
    def testAllowAll(self):
        """anything should be allowed by the AllowAll module."""
        self.assertTrue(allowall.allowed("bob", "do_this", params))
        
    def testDenyAll(self):
        """nothing should be allowed by the DenyAll module."""
        self.assertFalse(denyall.allowed("bob", "do_this", params))

    def testUserMovesTheirCard(self):
        """A user can move a card that they control"""
        self.assertTrue(thegame.move_card_coordinates("bob", 3, 2, {'x':1.5, 'y':1.3}))
        
    def testUserMovesAnothersCard(self):
        """A user cannot normally move a card that they do not control."""
        self.assertFalse(thegame.move_card_coordinates("jeff", 3, 2, {'x':1.5, 'y':1.3}))

    def testNoSuchUser(self):
        """Raise an error when asked for a non-existent user."""
        self.assertRaises(errors.NoSuchUserError, thegame.move_card_coordinates,
                          "curly", 3, 2, {'x':1.5, 'y':1.3})
        
    def testNoSuchPermissions(self):
        """Raise an error when asked about an unaddressed permission."""
        self.assertRaises(permissions.NoSuchPermissionsError, thegame.bad_action, "bob")
    
class CardCollectionTest(unittest.TestCase):
    def testCardOnTable(self):
        """This card should be on this table."""
        self.assertTrue(thegame.card_on_table("bob", "table1", "CardA"))
        
    def testCardOffTable(self):
        """This card should not be on this table."""
        self.assertFalse(thegame.card_on_table("bob", "table1", "CardD"))
        
    def testRemovedCardFromTableSuccessfully(self):
        """This card removal should both succeed and then the card should be  reported as gone."""
        self.assertTrue(thegame.remove_card_from_table("bob", "table1", "CardA"))
        self.assertFalse(thegame.card_on_table("bob", "table1", "CardA"))
        
    def testCannotRemoveCardNotOnTable(self):
        """We should not be able to remove a card that was not on the table in the first place."""
        self.assertRaises(errors.NoSuchCardError, thegame.remove_card_from_table,
                          "bob", "table1", "CardD")
        
    def testCardInDeck(self):
        """We should find this card in this deck."""
        self.assertTrue(thegame.card_in_deck("bob", "drawdeck1", "Card1"))
        
    def testCardNotInDeck(self):
        """We should not find this card in this deck."""
        self.assertFalse(thegame.card_in_deck("bob", "drawdeck1", "Card4"))
        
    def testRemovedCardFromDeckSuccessfully(self):
        """This card removal should both succeed and then the card should be reported as gone."""
        self.assertTrue(thegame.remove_card_from_deck("bob", "drawdeck1", "Card1"))
        self.assertFalse(thegame.card_in_deck("bob", "drawdeck1", "Card1"))
        
    def testCannotRemoveCardNotInDeck(self):
        """We should not be able to remove a card that was not in the deck in the first place."""
        self.assertRaises(errors.NoSuchCardError, thegame.remove_card_from_deck,
                          "bob", "drawdeck1", "Card4")
    
class ConnectionsTest(unittest.TestCase):
    def testSimpleEcho(self):
        command = "this is a command"
        theconnections.send_command("bob", command)

if __name__ == "__main__":
    unittest.main()